#include <iostream>
using std::cout;
using std::endl;
using std::string;

#if 0
int add(int x, int y)
{
    return x + y;
}

double add(double x, double y)
{
    return x + y;
}

long add(long x, long y)
{
    return x + y;
}

string add(string x, string y)
{
    return x + y;
}
#endif

/* auto add(int x, int y){ */
/*     return x + y; */
/* } */

//函数模板与函数模板重载
//模板参数个数不同,ok
template <class T>
T add(T t1,T t2)
{ return t1 + t2; }

//模板参数中函数返回值类型与函数第一个参数类型相同
template <class T1, class T2>
T1 add(T1 t1, T2 t2)
{
    return t1 + t2;
}

//模板参数中函数返回值类型与函数第二个参数类型相同
template <class T2, class T1>
T1 add(T2 t2, T1 t1)
{
    return t1 + t2;
}

template <class T1, class T2, class T3>
T1 add(T1 t1, T2 t2, T3 t3)
{
    return t1 + t2 + t3;
}

void test0(){
    /* auto p = new int(1); */
    short s1 = 1, s2 = 2;
    int i1 = 3, i2 = 4;
    long l1 = 5, l2 = 6;
    double d1 = 1.1, d2 = 2.2;

#if 0
    //如果只有第一个函数模板(模板参数只有一个)，进行如下调用

    //隐式实例化
    cout << "add(s1,s2): " << add(s1,s2) << endl;
    //显式实例化，在函数名之后，直接写上模板的实参列表
    //指定要生成的类型
    cout << "add(i1,i2): " << add<int>(i1,i2) << endl;
    cout << "add(l1,l2): " << add(l1,l2) << endl;
    cout << "add(d1,d2): " << add(d1,d2) << endl;
    //推导出的两个参数一个short型，一个是int型，发现没有对应的模板
    //函数模板生成不了能够处理的模板函数
    //cout << "add(s1,i2): " << add(s1,i2) << endl;//error
    
    cout << endl;
    //指定了类型T为int型，虽然s1是short型数据，但是会发生类型转换
    //这个转换没有问题，因为int肯定能存放short型数据的所有内容
    cout << "add(s1,i2): " << add<int>(s1,i2) << endl;
    //这里也会发生类型转换，将d1转换成int型，损失了精度
    cout << "add(d1,i2): " << add<int>(d1,i2) << endl;
#endif

    cout << endl;
    cout << "add(d1,i2): " << add<int>(d1,i2) << endl;
}

int main(void){
    test0();
    return 0;
}
